package com.ruoyi.tongban.utils;

import com.google.gson.Gson;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.tongban.result.AccessToken;
import org.apache.catalina.security.SecurityUtil;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 微信相关工具类
 * @Description
 * @Author caiyanshan
 * @Date 2020/10/16 10:37
 * @Param
 * @Return
 */
public class WechatUtil {
  
  private static String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
  private static String appId = "";
  private static String secret = "";
  private static String grantType = "grant_type=client_credential";
  private final static Logger logger = LoggerFactory.getLogger(WechatUtil.class);
  private static Lock lock = new ReentrantLock();
  
  private static ISysConfigService iSysConfigService;
  
  private static RedisCache redis;
  
  private static RedisCache getRedisCache(){
    if(redis == null){
      redis = SpringUtils.getBean(RedisCache.class);
    }
    return redis;
  }
  
  private static ISysConfigService getSysConfig(){
    if(iSysConfigService == null){
      iSysConfigService = SpringUtils.getBean(ISysConfigService.class);
    }
    return iSysConfigService;
  }
  
  private static void init() {
    appId = getSysConfig().selectConfigByKey("applets.appId");
    secret = getSysConfig().selectConfigByKey("applets.secret");
    logger.info("the server install wechat param: ");
    logger.info("appId is : " + appId);
    logger.info("secret is : " + secret);
  }
  
  /**
   * @Description 获取微信token
   * 有效期目前为 2 个小时，需定时刷新，重复获取将导致上次获取的 access_token 失效。
   * 当前时间减掉token获取时间小于2小时，即为有效。
   * @Author caiyanshan
   * @Date 2020/10/16 10:38
   * @Param []
   * @Return java.lang.String
   */
  public static String getAccessToken(){
    if(StringUtils.isBlank(appId) || StringUtils.isBlank(secret)){
      init();
    }
    AccessToken token = null;
    try{
      lock.lock();
      String key = "weixinToken";
      token = getRedisCache().getCacheObject(key);
      if(token == null){//数据为空要重新获取
        token = handleToken();
        logger.info("首次获取token数据，结果为:" + token.getToken());
        getRedisCache().setCacheObject(key, token, 60, TimeUnit.MINUTES);
        return token.getToken();
      }
      if(token.isExpire()){ // 过期，重新获取
        token = handleToken();
        logger.info("token数据已过期，再次获取数据结果为:" + token.getToken());
        getRedisCache().setCacheObject(key, token, 60, TimeUnit.MINUTES);
        return token.getToken();
      }
    }finally {
      lock.unlock();//必须解锁
    }
    logger.info("缓存中获取token,数据为:" + token.getToken());
    return token.getToken();
  }
  
  /**
   * @Description 发送请求获取token
   * @Author caiyanshan
   * @Date 2020/10/16 10:55
   * @Param []
   * @Return
   */
  private static AccessToken handleToken() {
    String param =  grantType+ "&appid=" + appId + "&secret=" +secret;
    String result = HttpUtils.sendGet(tokenUrl, param);
    logger.info("本次请求微信的token结果为: " +result);
    Gson gs = new Gson();
    AccessToken token = gs.fromJson(result, AccessToken.class);
    token.setStartTime(new Date());//重新获取需复制开始时间
    return token;
  }
}